﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestAppRedo
{
	public class Graph : IEnumerable<Node>
	{
		public Node GetNode(Person person)
		{
			Node node;
			m_personToNode.TryGetValue(person, out node);
			return node;
		}
		public Node AddNode(string name)
		{
			Person person = new Person();
			person.FirstName = name;
			return AddNode(person);
		}
		public Node AddNode(Person person)
		{
			Node node;
			if (!m_personToNode.TryGetValue(person, out node))
			{
				node = new Node(person);
				m_personToNode.Add(person, node);
			}
			return node;
		}
		public void AddEdge(string name1, string name2)
		{
			Person p1 = m_personToNode.Keys.First(p => p.FirstName == name1);
			Person p2 = m_personToNode.Keys.FirstOrDefault(p => p.FirstName == name2);
			AddEdge(p1, p2, Relation.Unknown);
		}
		public void AddEdge(Person p1, Person p2, Relation relation)
		{
			AddEdge(GetNode(p1), GetNode(p2), relation);
		}
		public void AddEdge(Node n1, Node n2, Relation relation)
		{
			if (n1 == null || n2 == null)
				return;

			n1.AddEdge(n2, relation);
		}
		SortedDictionary<Person, Node> m_personToNode = new SortedDictionary<Person, Node>();

		#region IEnumerable<Node> Members

		public IEnumerator<Node> GetEnumerator()
		{
			return m_personToNode.Values.GetEnumerator();
		}

		#endregion
		#region IEnumerable Members

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		#endregion
	}

	public class Node
	{
		public Node(Person person)
		{
			m_person = person;
		}
		public Person Person
		{
			get { return m_person; }
		}
		public IEnumerable<Edge> Edges
		{
			get { return m_edges; }
		}
		public void AddEdge(Node node, Relation relation)
		{
			m_edges.Add(new Edge(node, relation));
		}
		public override string ToString()
		{
			return string.Format("(Node) {0}", Person);
		}
		private Person m_person;
		private List<Edge> m_edges = new List<Edge>();
	}

	public class Edge
	{
		public Edge(Node node, Relation relation)
		{
			Node = node;
			Relation = relation;
		}

		public Node Node { get; set; }
		public Relation Relation { get; set; }
	}
}
